#include"tree.h"
#include"utility.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

TreeNode * TreeNode_create(char value,int freq){

    TreeNode * node = malloc(sizeof(TreeNode));
    // -must judy
    if(NULL == node){

        printf("malloc(sizeof(TreeNode)) failed.\n");
        return NULL;
    }
    node->value = value;
    node->freq = freq;
    node->left = NULL;
    node->right = NULL;

    return node;
}

// -tr1->freq < tr2->freq
TreeNode * TreeNode_merge(TreeNode * tr1,TreeNode * tr2){

    TreeNode * node = malloc(sizeof(TreeNode));
    node->freq = tr1->freq + tr2->freq;
    node->value = 0;
    node->left = tr1;
    node->right = tr2;

    return node;
}

void Tree_print(TreeNode * tn,int level){

    if(NULL!=tn){

        return;
    }
    Tree_print(tn->left,level + 1);
    Tree_print(tn->right,level + 1);
    for(int depth = 0;depth < level;depth++){

        printf("    ");
    }
    printf("freq = %d ",tn->freq);
    if(NULL == tn->right && NULL == tn->left){

        printf("value = %d, '%c'",tn->value,tn->value);
    }
    printf("\n");
}

static void countBinaryNodeHelper(TreeNode * tn,int * count){

    if(NULL == tn){

        return;
    }
    (*count)++;
    countBinaryNodeHelper(tn->left,count);
    countBinaryNodeHelper(tn->right,count);
}

// -统计节点
int countBinaryNode(TreeNode * tn){

    int count = 0;
    countBinaryNodeHelper(tn,&count);
    return count;
}

// 输出7位ASCII字符码
static void char2Bites(FILE * fptr,int ch,unsigned char * whichbit,unsigned char * curbyte){

    unsigned char mask = 0x40;
    while(mask > 0){

        writeBit(fptr,(ch & mask) == mask,whichbit,curbyte);
        mask = mask >> 1;
    }
}



static void
Tree_headerHelper(TreeNode * tn,FILE * outPtr,unsigned char * whichbit,unsigned char * curbyte){

    if(NULL == tn){

        return;
    }
    TreeNode * lc = tn->left;
    TreeNode * rc = tn->right;

    if(NULL == lc && NULL == rc){

        // fprintf(outPtr,"1%c",tn->value);
        writeBit(outPtr,1,whichbit,curbyte);
        char2Bites(outPtr,tn->value,whichbit,curbyte);
        return;
    }
    Tree_headerHelper(lc,outPtr,whichbit,curbyte);
    Tree_headerHelper(rc,outPtr,whichbit,curbyte);
    // -非叶子打印
    // fprintf(outPtr,"0");
    writeBit(outPtr,0,whichbit,curbyte);
}

// -构造头部结构
void Tree_header(TreeNode * tn,char * outfile){

    FILE * outPtr = fopen(outfile,"w");
    if(NULL == outPtr){

        return;
    }
    unsigned char whichbit = 0;
    unsigned char curbyte = 0;
    Tree_headerHelper(tn,outPtr,&whichbit,&curbyte);
    fprintf(outPtr,"0\n");
    fclose(outPtr);
}

int compress(char * infile,char * outfile,int ** codebook,int * mapping){

    FILE * infPtr = fopen(infile,"r");
    if(NULL == infPtr){

        printf("open %s file failed.\n",infile);
        return 0;
    }
    FILE * outfPtr = fopen(outfile,"a");    // apend
    if(NULL == outfPtr){

        printf("open %s file failed.\n",outfile);
        return 0;
    }
    while(!feof(infPtr)){

        int onechar = fgetc(infPtr);
        if(EOF != onechar){

            int ind = mapping[onechar];
            int index2 = 1;
            while (-1!=codebook[ind][index2])
            {
                fprintf(outfPtr,"%d",codebook[ind][index2]);
                index2++;
            }
        }
    }
    fclose(infPtr);
    fclose(outfPtr);
    return 1;
}
